package com.eedi.framework.info.framework.org;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.id.NanoId;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.eedi.framework.info.controller.org.vo.*;
import com.eedi.framework.biz.config.BizProperties;
import com.eedi.framework.common.enums.CommonStatusEnum;
import com.eedi.framework.common.pojo.PageResult;
import com.eedi.framework.info.convert.OrgInfoConvert;
import com.eedi.framework.info.service.OrgInfoService;
import com.eedi.framework.oauth2.controller.org.vo.client.OrgOAuth2ClientSaveReqVO;
import com.eedi.framework.oauth2.service.OrgOAuth2ClientService;
import com.eedi.framework.org.controller.sys.vo.*;
import com.eedi.framework.org.service.SysOrgService;
import com.eedi.framework.permission.controller.org.vo.role.SysOrgRoleCreateReq;
import com.eedi.framework.permission.dal.dataobject.OrgRoleDO;
import com.eedi.framework.permission.enums.OrgRoleCodeEnum;
import com.eedi.framework.permission.enums.OrgRoleTypeEnum;
import com.eedi.framework.permission.service.OrgPermissionService;
import com.eedi.framework.template.service.SysTemplateRoleService;
import com.eedi.framework.user.controller.org.vo.OrgUserAccountCreateReq;
import com.eedi.framework.user.controller.org.vo.OrgUserLoginInfoResp;
import com.eedi.framework.user.service.OrgUserService;
import com.eedi.framework.web.core.util.WebFrameworkUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

import static com.eedi.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.eedi.framework.info.enums.OrgInfoErrorCodeConstants.ORG_ADMIN_ROLE_IS_NULL;

@Service
public class SysOrgServiceImpl implements SysOrgService {

    @Resource
    BizProperties bizProperties;
    @Resource
    OrgInfoService orgInfoService;
    @Resource
    OrgOAuth2ClientService orgOauth2ClientService;
    @Resource
    OrgUserService orgUserService;
    @Resource
    OrgPermissionService orgPermissionService;
    @Resource
    private SysTemplateRoleService sysTemplateRoleService;

    @Override
    public PageResult<SysOrgInfoResp> page(SysOrgPageReq req) {
        OrgInfoPageReq reqVO = BeanUtil.toBean(req, OrgInfoPageReq.class);
        PageResult<OrgInfoResp> page = orgInfoService.page(reqVO);
        return page.convertPage(OrgInfoConvert.INSTANCE::convert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysOrgCreateResp create(SysOrgCreateReq req,String sysTenantId) {

        //1. 创建机构信息
        OrgInfoCreateReq orgInfoCreateReq = BeanUtil.toBean(req, OrgInfoCreateReq.class);
        orgInfoCreateReq.setOrgInfoStatus(CommonStatusEnum.ENABLE);
        OrgInfoResp orgInfoResp = orgInfoService.create(orgInfoCreateReq);


        //2. 给机构配置Oauth2的信息
        OrgOAuth2ClientSaveReqVO orgOauth2ClientSaveReq =  new OrgOAuth2ClientSaveReqVO();
        initDefaultOauth2Client(orgInfoResp,orgOauth2ClientSaveReq);
        String orgOauth2ClientId = orgOauth2ClientService.createOAuth2Client(orgOauth2ClientSaveReq);

        //3. 初始化机构下的账号信息
        OrgUserAccountCreateReq orgUserAccountCreateReq = new OrgUserAccountCreateReq();
        initDefaultOrgAdminAccount(req,orgInfoResp,orgUserAccountCreateReq);
        OrgUserLoginInfoResp orgUserLoginInfoResp = orgUserService.create(orgUserAccountCreateReq);

        //4. 初始化机构下的角色信息
//        //4.1 初始化机构下的超管角色
        SysOrgRoleCreateReq orgRoleAdmin = initDefaultOrgRole(orgInfoResp);
        String orgRoleAdminId = orgPermissionService.createRole(orgRoleAdmin);
        //4.2 初始化机构下的预设角色
        Map<String, String> orgRoleIdMap = orgPermissionService.presupposeRole(orgInfoResp.getOrgInfoId());
        //5. 给该账号分配默认系统管理角色
        //首先获取角色列表,并过滤出是超管的角色
        List<OrgRoleDO> listOrgRoles = orgPermissionService.getRoleListByOrgInfoIdAndRoleCode(orgInfoResp.getOrgInfoId(),OrgRoleCodeEnum.ORG_ADMIN);
        Set<String> orgRoleIds = new HashSet<>();
        listOrgRoles.forEach(orgRoleDO -> orgRoleIds.add(orgRoleDO.getOrgRoleId()));
        if (CollUtil.isEmpty(orgRoleIds)){
            throw exception(ORG_ADMIN_ROLE_IS_NULL);
        }
        // 然后给机构账号授予超管的角色
        orgPermissionService.assignUserRole(orgUserLoginInfoResp.getOrgUserId(),orgRoleIds,orgInfoResp.getOrgInfoId());
        //6. 初始化机构下的菜单信息
        Map<String,String>  menuIdMap= orgPermissionService.initOrgInfoDefaultMenus(orgInfoResp.getOrgInfoId());
        //7. 给默认角色设置菜单权限
//        orgPermissionService.assignRoleMenuByOrgInfoId(orgInfoResp.getOrgInfoId(),orgRoleAdminId,menuIdMap);
        orgPermissionService.assignDefaultRoleMenu(orgInfoResp.getOrgInfoId(),menuIdMap,orgRoleIdMap);

        //8. 组织返回对象
        SysOrgCreateResp resp = initSysOrgCreateResp(orgInfoResp,orgOauth2ClientSaveReq,orgUserLoginInfoResp,sysTenantId);
        return resp;
    }


    @Override
    public String resetPassword(String orgUserId) {
       return orgUserService.resetPassword(orgUserId);
    }

    @Override
    public SysOrgInfoDetailsResp get(String orgInfoId) {
        OrgInfoResp orgInfoResp = orgInfoService.getByOrgInfoId(orgInfoId);
        List<OrgInfoAdminUserResp> adminUsers = orgInfoService.listOrgInfoAdminUsers(orgInfoId);
        SysOrgInfoDetailsResp sysOrgInfoDetailsResp = new SysOrgInfoDetailsResp();
        assembleSysOrgInfoDetailsResp(sysOrgInfoDetailsResp,orgInfoResp,adminUsers);
        return sysOrgInfoDetailsResp;
    }

    @Override
    public Long countSysOrgInfo() {
        return orgInfoService.countOrgInfos();
    }

    @Override
    public void updateOrgInfo(SysOrgUpReq req) {
        OrgInfoUpdateReq orgInfoUpdateReq = BeanUtil.toBean(req, OrgInfoUpdateReq.class);
        orgInfoService.update(orgInfoUpdateReq);
    }

    private void assembleSysOrgInfoDetailsResp(SysOrgInfoDetailsResp sysOrgInfoDetailsResp, OrgInfoResp orgInfoResp, List<OrgInfoAdminUserResp> adminUsers) {
        sysOrgInfoDetailsResp.setOrgInfoId(orgInfoResp.getOrgInfoId());
        sysOrgInfoDetailsResp.setOrgName(orgInfoResp.getOrgName());
        sysOrgInfoDetailsResp.setOrgUscCode(orgInfoResp.getOrgUscCode());
        sysOrgInfoDetailsResp.setOrgInfoStatus(orgInfoResp.getOrgInfoStatus());
        sysOrgInfoDetailsResp.setOrgBusinessLicenseUrl(orgInfoResp.getOrgBusinessLicenseUrl());
        sysOrgInfoDetailsResp.setWebSite(bizProperties.getDefaultOrgUrl()+"/login?tenant-id="+ WebFrameworkUtils.getSysTenantId() + "&info-id=" + orgInfoResp.getOrgInfoId());
        sysOrgInfoDetailsResp.setOrgAdminUsers(OrgInfoConvert.INSTANCE.convertList(adminUsers));
    }

    private SysOrgCreateResp initSysOrgCreateResp(OrgInfoResp orgInfoResp,
                                                  OrgOAuth2ClientSaveReqVO orgOauth2ClientSaveReq,
                                                  OrgUserLoginInfoResp orgUserLoginInfoResp,
                                                  String sysTenantId) {
        SysOrgCreateResp resp = new SysOrgCreateResp();
        resp.setOrgInfoId(orgInfoResp.getOrgInfoId());
        resp.setOrgName(orgInfoResp.getOrgName());
        resp.setOrgAdminLoginId(orgUserLoginInfoResp.getOrgUserLoginId());
        resp.setOrgAdminPwd(bizProperties.getDefaultPasswd());
        resp.setWebSite(bizProperties.getDefaultOrgUrl()+"/login?tenant-id="+sysTenantId + "&info-id=" + orgInfoResp.getOrgInfoId());
        return resp;
    }

    private SysOrgRoleCreateReq initDefaultOrgRole(OrgInfoResp orgInfoResp) {
        //这里初始化创建系统默认角色
        SysOrgRoleCreateReq orgRoleAdmin = new SysOrgRoleCreateReq();
        orgRoleAdmin.setOrgInfoId(orgInfoResp.getOrgInfoId());
        orgRoleAdmin.setOrgRoleName("机构系统管理员角色");
        orgRoleAdmin.setOrgRoleCode(OrgRoleCodeEnum.ORG_ADMIN.getCode());
        orgRoleAdmin.setOrgRoleType(OrgRoleTypeEnum.SYSTEM);
        orgRoleAdmin.setOrgRoleSort(0);
        orgRoleAdmin.setOrgRoleRemark("机构初始化过程中自动创建系统管理员角色");
        orgRoleAdmin.setOrgRoleStatus(CommonStatusEnum.ENABLE);
        return orgRoleAdmin;
    }

    private void initDefaultOauth2Client(OrgInfoResp req,OrgOAuth2ClientSaveReqVO orgOauth2ClientSaveReq) {
        orgOauth2ClientSaveReq.setOrgInfoId(req.getOrgInfoId());
        orgOauth2ClientSaveReq.setName(req.getOrgName()+" OAUTH2应用");
        orgOauth2ClientSaveReq.setClientCode(NanoId.randomNanoId());
        orgOauth2ClientSaveReq.setSecret(NanoId.randomNanoId());
        orgOauth2ClientSaveReq.setLogo("http://www.hzeedi.com/oauth2.png");
        orgOauth2ClientSaveReq.setDescription(req.getOrgName()+" OAUTH2应用,是机构初始化过程中系统自动创建的一个应用，用于机构管理员登录系统使用，使用password模式进行。");
        orgOauth2ClientSaveReq.setStatus(CommonStatusEnum.ENABLE.getCode());
        orgOauth2ClientSaveReq.setAccessTokenValiditySeconds(1800);
        orgOauth2ClientSaveReq.setRefreshTokenValiditySeconds(2592000);
        List<String> redirectUris = new ArrayList<>();
        redirectUris.add("http://www.hzeedi.com");
        redirectUris.add("https://www.hzeedi.com");
        orgOauth2ClientSaveReq.setRedirectUris(redirectUris);
        List<String> authorizedGrantTypes = new ArrayList<>();
        authorizedGrantTypes.add("authorization_code");
        authorizedGrantTypes.add("password");
        authorizedGrantTypes.add("refresh_token");
        authorizedGrantTypes.add("implicit");
        orgOauth2ClientSaveReq.setAuthorizedGrantTypes(authorizedGrantTypes);
        List<String> scopes = new ArrayList<>();
        scopes.add("*");
        orgOauth2ClientSaveReq.setScopes(scopes);
        List<String> autoApproveScopes = new ArrayList<>();
        autoApproveScopes.add("*");
        orgOauth2ClientSaveReq.setAutoApproveScopes(autoApproveScopes);
        List<String> authorities = new ArrayList<>();
        authorities.add("*");
        orgOauth2ClientSaveReq.setAuthorities(authorities);
        List<String> resourceIds = new ArrayList<>();
        authorities.add("*");
        orgOauth2ClientSaveReq.setResourceIds(resourceIds);
        orgOauth2ClientSaveReq.setAdditionalInformation("{}");
    }
    private void initDefaultOrgAdminAccount(SysOrgCreateReq req,OrgInfoResp orgInfoResp,OrgUserAccountCreateReq orgUserAccountCreateReq) {
        orgUserAccountCreateReq.setOrgInfoId(orgInfoResp.getOrgInfoId());
        String orgUserLoginId = PinyinUtil.getFirstLetter(orgInfoResp.getOrgName(),"");
        orgUserAccountCreateReq.setOrgUserName("机构系统管理员");
        orgUserAccountCreateReq.setOrgUserLoginId(orgUserLoginId+"admin");
        orgUserAccountCreateReq.setOrgUserPassword(bizProperties.getDefaultPasswd());
        orgUserAccountCreateReq.setOrgUserMobile(req.getOrgAdminMobile());
    }

}
